package img

import (
	"testing"

	"github.com/veandco/go-sdl2/sdl"
)

var testBMP = []byte("BM\x96\x00\x00\x00\x00\x00\x00\x00\x92\x00\x00\x00|" +
	"\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x01\x00\x00\x00" +
	"\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00" +
	"\x00\x02\x00\x00\x00\x00\x00\xff\x00\x00\xff\x00\x00\xff\x00\x00\x00" +
	"\x00\x00\x00\xffBGRs\x8f\xc2\xf5(Q\xb8\x1e\x15\x1e\x85\xeb\x01333\x13ff" +
	"f&fff\x06\x99\x99\x99\t=\n\xd7\x03(\\\x8f2\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\x00\x80\x00\x00\x00")

var testGIF = []byte("GIF89a\x01\x00\x01\x00\xf0\x01\x00\x00\x00\x00\xff\xff" +
	"\xff!\xf9\x04\x00\x00\x00\x00\x00!\xff\vImageMagick\x0egamma=0.454545" +
	"\x00,\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02L\x01\x00;")

var testICO = []byte("\x00\x00\x01\x00\x01\x00\x01\x01\x02\x00\x01\x00\x01" +
	"\x008\x00\x00\x00\x16\x00\x00\x00(\x00\x00\x00\x01\x00\x00\x00\x02\x00" +
	"\x00\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00" +
	"\xff\xff\xff\x00\x80\x00\x00\x00\x00\x00\x00\x00")

var testJPG = []byte("\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01" +
	"\x00\x01\x00\x00\xff\xdb\x00C\x00\x03\x02\x02\x02\x02\x02\x03\x02\x02" +
	"\x02\x03\x03\x03\x03\x04\x06\x04\x04\x04\x04\x04\b\x06\x06\x05\x06\t\b" +
	"\n\n\t\b\t\t\n\f\x0f\f\n\v\x0e\v\t\t\r\x11\r\x0e\x0f\x10\x10\x11\x10\n" +
	"\f\x12\x13\x12\x10\x13\x0f\x10\x10\x10\xff\xc0\x00\v\b\x00\x01\x00\x01" +
	"\x01\x01\x11\x00\xff\xc4\x00\x14\x00\x01\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\t\xff\xc4\x00\x14\x10\x01\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xda\x00\b\x01" +
	"\x01\x00\x00?\x00T\xdf\xff\xd9")

// looks like a great file format!
var testPCX = []byte("\n\x05\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x01\x01\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\f\x00\x00\x00\xff" +
	"\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")

var testPNM = []byte("P4\n1 1\n\x00")

var testPNG = []byte("\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01" +
	"\x00\x00\x00\x01\x01\x00\x00\x00\x007n\xf9$\x00\x00\x00\x04gAMA\x00\x00" +
	"\xb1\x8f\v\xfca\x05\x00\x00\x00 cHRM\x00\x00z&\x00\x00\x80\x84\x00\x00" +
	"\xfa\x00\x00\x00\x80\xe8\x00\x00u0\x00\x00\xea`\x00\x00:\x98\x00\x00" +
	"\x17p\x9c\xbaQ<\x00\x00\x00\x02bKGD\x00\x01\u074a\x13\xa4\x00\x00\x00\a" +
	"tIME\a\xdf\a\x1c\x06\x186\xce\u007fA\x1f\x00\x00\x00\nIDAT\b\xd7ch\x00" +
	"\x00\x00\x82\x00\x81\xddCj\xf4\x00\x00\x00%tEXtdate:create\x002015-07-2" +
	"8T06:24:54-04:00\xc8\x17\xb4\x97\x00\x00\x00%tEXtdate:modify\x002015-07" +
	"-28T06:24:54-04:00\xb9J\f+\x00\x00\x00\x00IEND\xaeB`\x82")

var testTGA = []byte("\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" +
	"\x00\x01\x00\b\x00\xff")

var testTIF = []byte("II*\x00\x12\x00\x00\x00x\xdak\x00\x00\x00\x81\x00\x81" +
	"\x00\x0f\x00\x00\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x01" +
	"\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00\x02\x01\x03\x00\x01\x00\x00" +
	"\x00\x01\x00\x00\x00\x03\x01\x03\x00\x01\x00\x00\x00\b\x00\x00\x00\x06" +
	"\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00\n\x01\x03\x00\x01\x00\x00" +
	"\x00\x01\x00\x00\x00\x11\x01\x04\x00\x01\x00\x00\x00\b\x00\x00\x00\x12" +
	"\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00\x15\x01\x03\x00\x01\x00" +
	"\x00\x00\x01\x00\x00\x00\x16\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00" +
	"\x00\x17\x01\x04\x00\x01\x00\x00\x00\t\x00\x00\x00\x1c\x01\x03\x00\x01" +
	"\x00\x00\x00\x01\x00\x00\x00)\x01\x03\x00\x02\x00\x00\x00\x00\x00\x01" +
	"\x00>\x01\x05\x00\x02\x00\x00\x00\xfc\x00\x00\x00?\x01\x05\x00\x06\x00" +
	"\x00\x00\xcc\x00\x00\x00\x00\x00\x00\x00\x00\n\u05e3\xff\xff\xff\xff" +
	"\x80\xe1zT\xff\xff\xff\xff\x00\xcd\xccL\xff\xff\xff\xff\x00\x9a\x99\x99" +
	"\xff\xff\xff\xff\x80ff&\xff\xff\xff\xff\xf0(\\\x0f\xff\xff\xff\xff\x80" +
	"\x1b\rP\xff\xff\xff\xff\x00X9T\xff\xff\xff\xff")

var testWEBP = []byte("RIFF$\x00\x00\x00WEBPVP8 \x18\x00\x00\x000\x01\x00" +
	"\x9d\x01*\x01\x00\x01\x00\x02\x004%\xa4\x00\x03p\x00\xfe\xfb\x94\x00\x00")

var testXCF = []byte("gimp xcf file\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00" +
	"\x00\x00\x01\x00\x00\x00\x11\x00\x00\x00\x01\x01\x00\x00\x00\x13\x00" +
	"\x00\x00\bB\x90\x00\x00B\x90\x00\x00\x00\x00\x00\x14\x00\x00\x00\x04" +
	"\x00\x00\x00\x02\x00\x00\x00\x16\x00\x00\x00\x04\x00\x00\x00\x01\x00" +
	"\x00\x00\x15\x00\x00\x01B\x00\x00\x00\x10gimp-image-grid\x00\x00\x00" +
	"\x00\x01\x00\x00\x01\x00(style solid)\n(fgcolor (color-rgba 0.000000 0." +
	"000000 0.000000 1.000000))\n(bgcolor (color-rgba 1.000000 1.000000 1.00" +
	"0000 1.000000))\n(xspacing 10.000000)\n(yspacing 10.000000)\n(spacing-u" +
	"nit inches)\n(xoffset 0.000000)\n(yoffset 0.000000)\n(offset-unit inche" +
	"s)\n\x00\x00\x00\x00\x06gamma\x00\x00\x00\x00\x01\x00\x00\x00\x140.4545" +
	"5000000000001\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xa9\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00" +
	"\x00\x02\x00\x00\x00\ttest.png\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00" +
	"\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\xff\x00\x00\x00\b\x00\x00\x00" +
	"\x04\x00\x00\x00\x01\x00\x00\x00\t\x00\x00\x00\x04\x00\x00\x00\x00\x00" +
	"\x00\x00\x1c\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00" +
	"\x04\x00\x00\x00\x00\x00\x00\x00\v\x00\x00\x00\x04\x00\x00\x00\x00\x00" +
	"\x00\x00\f\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\r\x00\x00\x00" +
	"\x04\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00\b\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\a\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00" +
	"\x14\x00\x00\x00\x04\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x02b\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00" +
	"\x00\x01\x00\x00\x02v\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01" +
	"\x00\x00\x02\x86\x00\x00\x00\x00\x00\xff")

var testXPM = []byte(`/* XPM */
static char *test[] = {
/* columns rows colors chars-per-pixel */
"1 1 2 1 ",
"  c black",
". c white",
/* pixels */
"."
};
`)

var testBadData = []byte{0}

type isTest struct {
	name     string
	function func(*sdl.RWops) bool
	data     []byte
}

func TestIsFormat(t *testing.T) {
	Init(INIT_JPG | INIT_PNG | INIT_TIF | INIT_WEBP)
	defer Quit()

	functions := map[string](func(*sdl.RWops) bool){
		"BMP": IsBMP, "CUR": IsCUR, "GIF": IsGIF, "ICO": IsICO, "JPG": IsJPG,
		"LBM": IsLBM, "PCX": IsPCX, "PNG": IsPNG, "PNM": IsPNM, "TIF": IsTIF,
		"XCF": IsXCF, "XPM": IsXPM, "XV": IsXV, "WEBP": IsWEBP,
	}
	tests := []isTest{
		{"BMP", IsBMP, testBMP}, {"GIF", IsGIF, testGIF},
		{"ICO", IsICO, testICO}, {"JPG", IsJPG, testJPG},
		{"PCX", IsPCX, testPCX}, {"PNG", IsPNG, testPNG},
		{"PNM", IsPNM, testPNM}, {"TIF", IsTIF, testTIF},
		{"WEBP", IsWEBP, testWEBP}, {"XCF", IsXCF, testXCF},
		{"XPM", IsXPM, testXPM},
	}

	for _, test := range tests {
		rwops, _ := sdl.RWFromMem(test.data)
		for fname, function := range functions {
			got, want := function(rwops), fname == test.name
			if got != want {
				t.Errorf("%s: Is%s() == %v; want %v", test.name, fname, got,
					want)
			}
		}
	}
}

type loadTest struct {
	name     string
	function func(*sdl.RWops) (*sdl.Surface, error)
	data     []byte
}

func TestLoad_RW(t *testing.T) {
	defer Quit()

	// test expected success
	rwops, _ := sdl.RWFromMem(testPNG)
	surf, err := LoadRW(rwops, false)
	if surf != nil {
		defer surf.Free()
	}
	if surf == nil || err != nil {
		t.Errorf("LoadRW() == %v, %v; want surface without error", surf, err)
	}

	// test expected failure
	rwops, _ = sdl.RWFromMem(testBadData)
	surf, err = LoadRW(rwops, false)
	if surf != nil {
		defer surf.Free()
	}
	if surf != nil || err == nil {
		t.Errorf("LoadRW() == %v, %v; want error without surface", surf, err)
	}
}

func TestLoadFormat(t *testing.T) {
	defer Quit()

	tests := []loadTest{
		{"BMP", LoadBMPRW, testBMP}, {"GIF", LoadGIFRW, testGIF},
		{"ICO", LoadICORW, testICO}, {"JPG", LoadJPGRW, testJPG},
		{"PCX", LoadPCXRW, testPCX}, {"PNG", LoadPNGRW, testPNG},
		{"PNM", LoadPNMRW, testPNM}, {"TGA", LoadTGARW, testTGA},
		{"TIF", LoadTIFRW, testTIF}, {"XCF", LoadXCFRW, testXCF},
		{"XPM", LoadXPMRW, testXPM},
		// WEBP is undocumented and panics, so none of that.
	}

	for _, test := range tests {
		// test expected success
		rwops, _ := sdl.RWFromMem(test.data)
		surf, err := test.function(rwops)
		if surf != nil {
			defer surf.Free()
		}
		if surf == nil || err != nil {
			t.Errorf("Load%sRW() == %v, %v; want surface without error",
				test.name, surf, err)
		}

		// test expected failure... unless we're loading XCF, since XCF will
		// load anything.
		if test.name == "XCF" {
			continue
		}

		rwops, _ = sdl.RWFromMem(testBadData)
		surf, err = test.function(rwops)
		if surf != nil {
			defer surf.Free()
		}
		if surf != nil || err == nil {
			t.Errorf("Load%sRW() == %v, %v; want error without surface",
				test.name, surf, err)
		}
	}
}

func TestLoadTyped_RW(t *testing.T) {
	defer Quit()

	// test expected success
	rwops, _ := sdl.RWFromMem(testPNG)
	surf, err := LoadTypedRW(rwops, false, "PNG")
	if surf != nil {
		defer surf.Free()
	}
	if surf == nil || err != nil {
		t.Errorf("LoadTypedRW(%#v) == %v, %v; want surface without error",
			"PNG", surf, err)
	}

	// test expected failure
	rwops, _ = sdl.RWFromMem(testBadData)
	surf, err = LoadTypedRW(rwops, false, "PNG")
	if surf != nil {
		defer surf.Free()
	}
	if surf != nil || err == nil {
		t.Errorf("LoadTypedRW(%#v) == %v, %v; want error without surface",
			"PNG", surf, err)
	}
}
